# coding:utf-8
from typing import Union, List, Tuple

from PyQt6.QtCore import Qt, pyqtSignal, pyqtProperty, QRect, QRectF, QSize
from PyQt6.QtGui import QColor, QPainter, QPen, QBrush, QDropEvent, QPaintEvent, QFontMetrics, QIcon, QFont
from PyQt6.QtWidgets import QPushButton, QAbstractButton, QVBoxLayout, QLabel, QApplication, QWidget, QFileDialog
from multipledispatch import dispatch
from qfluentwidgets.common.icon import toQIcon, drawIcon
from qfluentwidgets.common.overload import singledispatchmethod
from qfluentwidgets import PushButton, FluentIconBase, FluentIcon, isDarkTheme, setFont

from common import StyleSheet, SingleIcon


class TransparentDirectionPushButton(QPushButton):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setFlat(True)
        StyleSheet.BUTTON.apply(self)

    def setAlignment(self, direction: Qt.AlignmentFlag):
        if direction == Qt.AlignmentFlag.AlignLeft:
            self.setProperty('alignment', 'left')
        elif direction == Qt.AlignmentFlag.AlignRight:
            self.setProperty('alignment', 'right')
        elif direction == Qt.AlignmentFlag.AlignCenter:
            self.setProperty('alignment', 'center')


class DragDropButton(QAbstractButton):
    fileChanged = pyqtSignal(str)

    @singledispatchmethod
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)
        self.__lineWidth = 3
        self.__xRadius = 5
        self.__yRadius = 5
        self.__borderColor = QColor(190, 190, 190, 200)
        self._icon = SingleIcon.UPLOAD
        self.__directory = './'
        self.__filter: list = []
        setFont(self, 20)
        self.setText('拖放或单击此处选择文件')
        self.setMinimumSize(300, 200)

        self.setAcceptDrops(True)
        self.clicked.connect(self._openDirection)
        self._postInit()

    @__init__.register
    def _(self, text: str, parent: QWidget = None, icon: Union[QIcon, str, FluentIconBase] = None):
        self.__init__(parent=parent)
        self.setText(text)
        self.setIcon(icon)

    @__init__.register
    def _(self, icon: QIcon, text: str, parent: QWidget = None):
        self.__init__(text, parent, icon)

    @__init__.register
    def _(self, icon: FluentIconBase, text: str, parent: QWidget = None):
        self.__init__(text, parent, icon)

    def _postInit(self):
        pass

    def setIcon(self, icon: Union[QIcon, str, FluentIconBase]):
        self.setStyle(QApplication.style())
        self._icon = icon or QIcon()
        self.update()

    def icon(self):
        return toQIcon(self._icon)

    def setLineWidth(self, width: int):
        self.__lineWidth = width
        self.update()

    def setBorderColor(self, color: QColor):
        self.__borderColor = color
        self.update()

    def getBorderColor(self) -> QColor:
        return self.__borderColor

    def _openDirection(self):
        if self.filter:
            tps = []
            for f in self.filter:
                tps.append(f'*.{f}')
            filter = '文件类型 (' + ' '.join(tps) + ')'
        else:
            filter = '所有文件 (*)'

        file, _ = QFileDialog.getOpenFileNames(self, '选择文件', self.directory, filter)
        for f in file:
            self.fileChanged.emit(f)

    @dispatch(int, int)
    def setRadius(self, xRadius: int, yRadius: int):
        self.__xRadius = xRadius
        self.__yRadius = yRadius
        self.update()

    @dispatch(int)
    def setRadius(self, radius: int):
        self.setRadius(radius, radius)

    def setDirectory(self, directory: str):
        self.__directory = directory

    def getDirectory(self) -> str:
        return self.__directory

    def setFilter(self, filter: Union[List[str], Tuple[str]]):
        self.__filter = filter

    def getFilter(self) -> Union[Tuple[str], List[str]]:
        return self.__filter

    def dragEnterEvent(self, event: QDropEvent):
        if event.mimeData().hasUrls():
            event.accept()
            self.repaint()
        else:
            event.ignore()

    def dropEvent(self, event: QDropEvent):
        mime = event.mimeData()
        if mime.hasUrls():
            for url in mime.urls():
                self.fileChanged.emit(url.toLocalFile())
        self.repaint()

    def paintEvent(self, event: QPaintEvent):
        painter = QPainter(self)
        painter.setRenderHints(QPainter.RenderHint.Antialiasing | QPainter.RenderHint.TextAntialiasing)

        pen = QPen(self.borderColor, self.__lineWidth, Qt.PenStyle.DashLine, Qt.PenCapStyle.RoundCap)
        painter.setPen(pen)
        painter.drawRoundedRect(self.rect(), self.__xRadius, self.__yRadius)

        fontMetrics = QFontMetrics(self.font())
        text = fontMetrics.elidedText(self.text(), Qt.TextElideMode.ElideRight, self.width() - 20)
        rect = self.rect()
        iconRect = rect.adjusted(10, 10, -10, -10 - fontMetrics.height() - 20)
        drawIcon(self.icon(), painter, iconRect, state=QIcon.State.Off)
        if isDarkTheme():
            painter.setPen(QColor(255, 255, 255))
        else:
            painter.setPen(QColor(0, 0, 0))
        painter.drawText(rect.adjusted(10, iconRect.y() + iconRect.height() - fontMetrics.height(), -10, -10),
                         Qt.AlignmentFlag.AlignCenter, text)
        painter.end()

    borderColor = pyqtProperty(QColor, getBorderColor, setBorderColor)
    directory = pyqtProperty(str, getDirectory, setDirectory)
    filter = pyqtProperty(str, getFilter, setFilter)


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    w = DragDropButton()
    w.setRadius(8)
    w.show()
    sys.exit(app.exec())
